﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.HomeServer.Controls;
using RouterControl.Whs.SingletonService;
using RouterControl.WhsAddIn.Wizards.EditPortForwarding;

namespace RouterControl.WhsAddIn.ConsoleControls
{
    public partial class PortForwarding : ConsoleControlBase
    {
        internal SingletonService2Factory SingeltonService
        {
            get { return _singletonService; }
        }

        public PortForwardingEntry SelectedEntry
        {
            get
            {
                return (
                    from PortForwardingEntry e in this.flowEntriesPanel.Controls
                    where e.Selected
                    select e
                    ).FirstOrDefault();
            }
        }

        public PortForwarding(RouterControlConsoleTab2 tab)
			: base(tab)
		{
			if (_log.IsDebugEnabled)
				_log.Debug("Initialization start");

			try
			{
				InitializeComponent();
	
				this.lineBox.Header.Text = Properties.Resources.txtPortForwarding;

				// done
				if (_log.IsDebugEnabled)
					_log.Debug("Initialization done");
			}
			catch (Exception e)
			{
				_log.Fatal("Failed to initialize", e);

				throw;
			}
		}

        private void PortForwarding_Load(object sender, EventArgs e)
        {
            if (!_singletonService.Channel.IsSelectedDeviceFound())
            {
                _log.Warn("no device selected");

                _tab.ResetState();

                return;
            }

            // load forwardings
            LoadAndUpdatePortForwardings();

            this.timerUpdateForwards.Enabled = true;
        }

        private void LoadAndUpdatePortForwardings()
        {
            // prepare
            var fwds = _singletonService.Channel.GetPortForwardingsEx();

            if (fwds == null)
                return;

            this.flowEntriesPanel.SuspendLayout();

            // gather existing
            var unhandledEntries = new List<PortForwardingEntry>(
                from PortForwardingEntry c in this.flowEntriesPanel.Controls
                select c
                );

            foreach (var fwd in fwds)
            {
                // entry exists?
                var exists = (
                    from c in unhandledEntries
                    where c.ForwardingId == fwd.Forwarding.Id
                    select c
                    ).FirstOrDefault();

                if (exists != null)
                {
                    exists.UpdateFrom(fwd.Forwarding);
                    exists.SetApprovalStatus(fwd.Approved);

                    // remove from unhandled list
                    unhandledEntries.Remove(exists);
                }
                else
                {
                    try
                    {
                        var pe = new PortForwardingEntry(this, fwd.Forwarding);

                        pe.SetApprovalStatus(fwd.Approved);

	                    this.flowEntriesPanel.Controls.Add(pe);
                    }
                    catch (Exception ex)
                    {
                        _log.Error("Failed to create new port forwarding entry (GUI)", ex);

                        // ignore; the entry will not be shown
                        // automatic error reporting is enough here
                    }
                }
            }

            // drop unhandled entries
            foreach (var c in unhandledEntries)
            {
                this.flowEntriesPanel.Controls.Remove(c);
            }

            // reset colors
            bool gray = false;

            foreach (PortForwardingEntry fwd in this.flowEntriesPanel.Controls)
            {
                gray = !gray;

                fwd.UnselectedBackcolor = (gray ? Color.WhiteSmoke : Color.White);
            }

            this.flowEntriesPanel.ResumeLayout();
        }

        private void timerUpdateForwards_Tick(object sender, EventArgs e)
        {
            try
            {
	            // pre-checks
	            if (_singletonService.IsWindowsServiceRunning() != SingletonService2Factory.ServiceStatus.Running)
	                return;
	
	            // update
	            LoadAndUpdatePortForwardings();
            }
            catch (Exception ex)
            {
                _log.Error("Failed to load and update port forwardings", ex);

                throw;
            }
        }

        private void createNewLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
	            var wiz = new WizardMain();
	
	            wiz.Run();
            }
            catch (Exception ex)
            {
                _log.Error("Failed to run edit-port-forwarding wizard", ex);
            }
        }

        private void clearApprovalsLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
                var r = Microsoft.HomeServer.Controls.QMessageBox.Show(
                    Properties.Resources.txtPortForwardingApprovalsClearAllDesc,
                    Properties.Resources.txtPortForwardingApprovalsClearAllTitle,
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Warning
                    );

                if (r == DialogResult.Yes)
                {
                    _singletonService.Channel.ClearAllPortForwardingApprovals();
                }
            }
            catch (Exception ex)
            {
                _log.Error("Failed to clear port forwarding approvals", ex);

                Microsoft.HomeServer.Controls.QMessageBox.Show(
                    ex.Message,
                    Properties.Resources.txtPortForwardingApprovalsClearFailedTitle,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                    );
            }
        }
    }
}
